import { RepoLink, Link, FileAdded, Warning } from '@brillout/docpress'
import { Example, UseScaffolder } from '../../components'
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'
import '../../components/tabs.css'
import Examples from './Examples.mdx'
import { PhotonBuiltInServer, PhotonBetaWarning, PhotonAutoLoad, PhotonDeploymentProviderIntroPart1, PhotonDeploymentProviderIntroPart2 } from '../vike-photon/components'

{/* See https://github.com/vikejs/vike/pull/2605 for a test of applying the following vike-cloudflare install instructions to packages/create-vike-core/boilerplate-react/ and examples/react-full/ */ }

<PhotonDeploymentProviderIntroPart1 provider="Cloudflare" link="https://www.cloudflare.com" />

> In development, your server code runs inside `workerd` (the runtime Cloudflare uses in production), so you're developing in an environment similar to production. This is a <Link href="/blog/photon#cloudflare">new Cloudflare feature that Photon supports</Link>.

<PhotonDeploymentProviderIntroPart2 provider="Cloudflare" />


## Get started

### New app

<UseScaffolder>Cloudflare with Photon</UseScaffolder>

### Add to existing app

> If you're using `vike-server` then  <Link href="/migration/vike-photon">migrate to `vike-photon`</Link>.

#### 1. Install

<Tabs>
  <TabList>
    <Tab>npm</Tab>
    <Tab>pnpm</Tab>
    <Tab>yarn</Tab>
  </TabList>
  <TabPanel>
    ```shell
    npm i wrangler vike-photon @photonjs/cloudflare
    ```
  </TabPanel>
  <TabPanel>
    ```shell
    pnpm add wrangler vike-photon @photonjs/cloudflare
    ```
  </TabPanel>
  <TabPanel>
    ```shell
    yarn add wrangler vike-photon @photonjs/cloudflare
    ```
  </TabPanel>
</Tabs>

```ts
// pages/+config.ts

import type { Config } from 'vike/types'
import vikePhoton from 'vike-photon/config'// [!code ++]

export default {
  extends: [vikePhoton]// [!code ++]
} satisfies Config
```

<PhotonAutoLoad pkg="cloudflare" />

#### 2. Scripts

```json
// package.json

{
  "scripts": {
    "dev": "vike dev",
    "preview": "vike build && vike preview",// [!code ++]
    "deploy": "vike build && wrangler deploy"// [!code ++]
  }
}
```

#### 3. Wrangler config

<FileAdded>
```jsonc
// wrangler.jsonc

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "compatibility_date": "2025-08-06",
  "name": "my-vike-cloudflare-app",
  "main": "virtual:photon:cloudflare:server-entry",
  // Only required if your app (or one of your libraries) uses a Node.js API
  "compatibility_flags": ["nodejs_compat"]
}
```
</FileAdded>

```bash
# .gitignore

.wrangler/ # [!code ++]
```

#### 4. Server (optional)

<PhotonBuiltInServer />


## Cloudflare APIs

To access Cloudflare APIs (such as [D1](https://developers.cloudflare.com/d1/) and [KV](https://developers.cloudflare.com/kv/)), use [Cloudflare's bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/) which are available via the `env` object [imported from `cloudflare:workers`](https://developers.cloudflare.com/workers/runtime-apis/bindings/#importing-env-as-a-global).

```ts
// Environment: server

import { env } from 'cloudflare:workers'
// Key-value store
env.KV.get('my-key')
// Environment variable
env.LOG_LEVEL
// ...
```

> Example of using [Cloudflare D1](https://developers.cloudflare.com/d1/):
> <Tabs>
>   <TabList>
>     <Tab>npm</Tab>
>     <Tab>pnpm</Tab>
>     <Tab>yarn</Tab>
>   </TabList>
>   <TabPanel>
>     ```shell
>     npm create vike@latest --- --react --hono --drizzle --cloudflare
>     ```
>   </TabPanel>
>   <TabPanel>
>     ```shell
>     pnpm create vike@latest --react --hono --drizzle --cloudflare
>     ```
>   </TabPanel>
>   <TabPanel>
>     ```shell
>     yarn create vike@latest --react --hono --drizzle --cloudflare
>     ```
>   </TabPanel>
> </Tabs>
>
> Or go to <Link href="/new">vike.dev/new</Link> and select `Cloudflare` with an ORM.

> To make environment variables available on the client-side, you can use <Link href="/onCreateGlobalContext">+onCreateGlobalContext.server.js</Link> with a <Link href="/globalContext#custom">custom `globalContext` property</Link> and <Link href="/passToClient">`passToClient`</Link>.
>
> ```ts
> // pages/+onCreateGlobalContext.server.ts
> // Environment: server
>
> export { onCreateGlobalContext }
>
> import { env } from 'cloudflare:workers'
> import type { GlobalContextServer } from 'vike/types'
>
> async function onCreateGlobalContext(globalContext: GlobalContextServer) {
>   // Making the environment variable LOG_LEVEL available on the client-side
>   globalContext.logLevel = env.LOG_LEVEL || 'info'
> }
>
> declare global {
>   namespace Vike {
>     interface GlobalContext {
>       logLevel: string
>     }
>   }
> }
> ```
> ```ts
> // pages/+config.ts
>
> import type { Config } from 'vike/types'
>
> export default {
>   passToClient: ['logLevel']
> } satisfies Config
> ```
>
> ```ts
> // anywhere.ts
> // Environment: server and/or client
>
> import { getGlobalContext } from 'vike'
>
> const globalContext = getGlobalContext()
> // Available anywhere
> console.log(globalContext.logLevel)
> ```


## TypeScript

If you use TypeScript, run [`wrangler types`](https://developers.cloudflare.com/workers/wrangler/commands/#types) whenever you change your Cloudflare configuration to update the `worker-configuration.d.ts` file.

<Tabs>
  <TabList>
    <Tab>npm</Tab>
    <Tab>pnpm</Tab>
    <Tab>yarn</Tab>
  </TabList>
  <TabPanel>
    ```shell
    npx wrangler types
    ```
  </TabPanel>
  <TabPanel>
    ```shell
    pnpm wrangler types
    ```
  </TabPanel>
  <TabPanel>
    ```shell
    yarn wrangler types
    ```
  </TabPanel>
</Tabs>

Then commit:

```bash
git commit -am "update cloudflare types"
```

Make sure TypeScript loads it:

```jsonc
// tsconfig.json

{
  "compilerOptions": {
    "types": ["./worker-configuration.d.ts"]// [!code ++]
 }
}
```

See also: [Cloudflare Workers > TypeScript](https://developers.cloudflare.com/workers/languages/typescript/)

## Extend 3MB limit

By default the bundle size of your worker cannot exceed 3MB, but you can request sizes of up to 100MB and beyond.
 - [Cloudflare Workers > Larger Scripts](https://www.cloudflare.com/larger-scripts-on-workers-early-access/)
 - [Cloudflare Workers > Limits > Worker Size](https://developers.cloudflare.com/workers/platform/limits/#worker-size)


## Manual integration

Instead of using `vike-photon`, you can manually integrate your app with Cloudflare yourself.

### Cloudflare Pages

For a manual integration, we generally recommend using:
 - [Cloudflare Pages](https://developers.cloudflare.com/pages/) for static assets and <Link href="/pre-rendering">pre-rendered pages</Link>, and
 - [Pages Functions](https://developers.cloudflare.com/pages/platform/functions/) for <Link href="/ssr">SSR'd pages</Link>.

Examples:
 - <Example timestamp="2024.01" repo="travis-r6s/vike-cf-pages" /> - Advanced demo showcasing a lot of integrations such as REST, tRPC, GraphQL, Sentry, and Thumbprint.
 - <Example timestamp="2022.04" repo="Immortalin/vite-plugin-ssr-cloudflare-pages-demo" />
   > vite-plugin-ssr was the [previous name of Vike](https://vite-plugin-ssr.com/vike).

### Workers

You can also directly use [Cloudflare Workers](https://workers.cloudflare.com) instead of using Cloudflare Pages.

Cloudflare Workers requires your entire worker code to be bundled into a single file — you can use [Wrangler](https://github.com/cloudflare/workers-sdk) to achieve that (it uses [esbuild](https://esbuild.github.io/) under the hood).

> Cloudflare uses the term "worker code" to denote server code that is run on its edge infrastructure.

<Examples />

### Development

For a significantly faster development experience we recommend, whenever possible, using Vite's development server (or a server such as <Link href="/express">Express.js</Link> or <Link href="/hono">Hono</Link>) instead of Wrangler.

In other words:
 - Skip `wrangler` / Cloudflare Workers altogether while developing your app.
 - Use `wrangler dev` to preview your worker.
 - Use `wrangler publish` to deploy your worker to Cloudflare Workers.

<Examples />

#### Universal `fetch()`

When using Node.js(/Bun/Deno) for development and Cloudflare Workers for production, you may need a `fetch()` function that works in both environments.

You can define a fetch function at `pageContext.fetch` that works in all environments.
The trick is to add a different `fetch()` implementation to `pageContextInit` at <Link text={<code>renderPage(pageContextInit)</code>} href="/renderPage" />.

Example: <RepoLink path='/examples/cloudflare-workers-react-full#universal-fetch' />.

> Libraries such as `node-fetch` or `cross-fetch` typically don't work with Cloudflare Workers.


## See also

- <Link href="/cloudflare-pages" />
- [Cloudflare Workers](https://developers.cloudflare.com/workers/)
- [Cloudflare](https://cloudflare.com)
